//<<<+++OPENSOURCE
//<<<+++OPENSOURCE_LICENSE
/**
 * @addtogroup FPDFAPI
 * @{
 */

/**
 * @file
 * @brief Text extracting and searching, Link extracting.
 */
//<<<+++OPENSOURCE_MUST_BEGIN
#ifndef _FPDF_TEXT_H_
#define _FPDF_TEXT_H_

#ifndef _FPDF_PARSER_
#include "../fpdfapi/fpdf_parser.h"
#endif
#ifndef _FPDF_PAGEOBJ_H_
#include "../fpdfapi/fpdf_pageobj.h"
#endif
#ifndef _FPDF_PAGE_
#include "../fpdfapi/fpdf_page.h"
#endif
//<<<+++OPENSOURCE_MUST_END
class CPDF_PageObjects;

/**
 * @name OS Text extracting flags.
 */
/*@{*/

/** @brief Auto rotating. */
#define PDF2TXT_AUTO_ROTATE		1
/** @brief Auto width. */
#define PDF2TXT_AUTO_WIDTH		2
/** @brief Keep column. */
#define PDF2TXT_KEEP_COLUMN		4
/** @brief Whether to use OCR. */
#define PDF2TXT_USE_OCR			8
/** @brief Whether to include invisible texts. */
#define PDF2TXT_INCLUDE_INVISIBLE	16

/*@}*/

/**
* Function: PDF_GetPageText
*
* Comments:
*			Extract pure text from a page, in appearance order
*
* @param[in/out] lines		receive text
* @param[in] pDoc			A PDF Document handle
* @param[in] pPage			A PDF Page handle
* @param[in] iMinWidth	
* @param[in] flags			see Text extracting flags.
*
*/
void PDF_GetPageText(CFX_ByteStringArray& lines, CPDF_Document* pDoc, CPDF_Dictionary* pPage, 
					 int iMinWidth, FX_DWORD flags);

/**
* Function: PDF_GetPageText_Unicode
*
* Comments:
*			Extract Unicode pure text from a page, in appearance order
*
* @param[in/out] lines		receive text
* @param[in] pDoc			A PDF Document handle
* @param[in] pPage			A PDF Page handle
* @param[in] iMinWidth	
* @param[in] flags			see Text extracting flags.
*
*/
void PDF_GetPageText_Unicode(CFX_WideStringArray& lines, CPDF_Document* pDoc, CPDF_Dictionary* pPage, 
					 int iMinWidth, FX_DWORD flags);

/**
* Function: PDF_GetTextStream_Unicode
*
* Comments:
*			Extract Unicode pure text from a page, in stream order
*
* @param[in/out] buffer		receive text
* @param[in] pDoc			A PDF Document handle
* @param[in] pPage			A PDF Page handle
* @param[in] flags			see Text extracting flags.
*
*/
void PDF_GetTextStream_Unicode(CFX_WideTextBuf& buffer, CPDF_Document* pDoc, CPDF_Dictionary* pPage, 
							   FX_DWORD flags);

/**
* Function: PDF_GetTextStream_Unicode
*
* Comments:
*			Extract the first text line in stream order
*
* @param[in] pDoc			A PDF Document handle
* @param[in] pPage			A PDF Page handle
*
* @retval return the first text line.
*
*/
CFX_WideString PDF_GetFirstTextLine_Unicode(CPDF_Document* pDoc, CPDF_Dictionary* pPage);

//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
/** @brief A progressive search facility for stream-based text searching inside a single page */
class CPDF_ProgressiveSearch : public CFX_Object
{
public:
	/** The destructor. */
	virtual ~CPDF_ProgressiveSearch() {}

	/** @brief Searching status for progressive searching. */
	typedef enum {
		Ready,				/**< Ready. */
		ToBeContinued,		/**< To be continued. */
		Found,				/**< Found. */
		NotFound,			/**< Not found. */
		Failed				/**< Failed. */
	} SearchStatus;

	/** Get current status. */
	virtual SearchStatus	GetStatus() = 0;

	/** Function: CPDF_ProgressiveSearch::FindFrom
	*
	* Comments:
	*			Find the first match with specified search flags, optionally with a start position. 
	
	*
	* @param[in] pPage			A PDF Page handle
	* @param[in] findWhat		find string
	* @param[in] pos			start find pos
	* @param[in] flags			see Text extracting flags
	* @param[in] pPause			Pointer to a structure that can pause the finding process.
	* 							Can be NULL if no pausing is needed.
	*/
	virtual void	FindFrom(CPDF_Page* pPage, const CFX_WideString& findWhat,
						int pos, FX_DWORD flags, IFX_Pause* pPause) = 0;

	/** Continue the searching. */
	virtual void	Continue() = 0;

	/**
	 * @name Search for next or previous match within the same page, from last match position.
	 * These two functions can't be paused.
	 */
	/*@{*/

	/** Search for next match within the same page, from last match position. */
	virtual void	FindNext() = 0;
	/** Search for previous match within the same page, from last match position. */
	virtual void	FindPrev() = 0;

	/*@}*/

	/**
	 * @name Get rectangles (in PDF coordinations) for current found match (if any).
	 * Before these functions can be called, the page must be parsed.
	 */
	/*@{*/

	/** Get the count of rectangles for current found matches. */
	virtual FX_DWORD	CountRects() = 0;
	/** Get the specified rectangle for current found matches. */ 
	virtual CFX_FloatRect	GetRect(int index) = 0;

	/*@}*/

	/** Get the current position. */
	virtual int		GetPos() = 0;
};

/** Create a progressive searching object. */
CPDF_ProgressiveSearch* FPDF_CreateTextSearch();
//<<<+++OPENSOURCE_END
class IPDF_TextPage;
class IPDF_LinkExtract;
class IPDF_TextPageFind;

//////////////////////////////////////////////////////////////////////////
//IPDF_TextPage
//char info

// char info flag:
#define CHAR_ERROR			-1	/**< error. */
#define CHAR_NORMAL			0	/**< normal. */
#define CHAR_GENERATED		1	/**< generated. */
#define CHAR_UNUNICODE		2	/**< error. */
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
#define CHAR_HYPHEN			3	/**< hyphen. */
#define CHAR_COMBOWORD		4	/**< Combination word. */
//<<<+++OPENSOURCE_END

/** @brief Character info for IPDF_TextPage. */
typedef struct _FPDF_CHAR_INFO
{
//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
public:
	_FPDF_CHAR_INFO()
	{
		m_Unicode = 0;
		m_Charcode = 0;
		m_Flag = 0;
		m_FontSize = 0;
		m_OriginX = 0;
		m_OriginY = 0;
		m_pTextObj = 0;
	}
	//<<<+++OPENSOURCE_END
	FX_WCHAR			m_Unicode;		/**< Unicode for the character. */
	FX_WCHAR			m_Charcode;		/**< Charcode for the character. */
	FX_INT32			m_Flag;			/**< character's flag. */
	FX_FLOAT			m_FontSize;		/**< The font size. */
	FX_FLOAT			m_OriginX;		/**< The x-coordinate of the origin position. */
	FX_FLOAT			m_OriginY;		/**< The y-coordinate of the origin position. */
	CFX_FloatRect		m_CharBox;		/**< The character box. int page space. */
	CPDF_TextObject*	m_pTextObj;		/**< Which text object it belongs to. */
	CFX_AffineMatrix	m_Matrix;		/**< The matrix. */
} FPDF_CHAR_INFO;

/** @brief Rectangle array. */
typedef	CFX_ArrayTemplate<CFX_FloatRect> CFX_RectArray;

/**
 * @name Flags for CreateTextPage.
 */
/*@{*/

#define FPDFTEXT_LRTB	0
#define FPDFTEXT_RLTB	1
#define FPDFTEXT_TBRL	2

/*@}*/

/**
 * @name Directions type.
 */
/*@{*/

/** @brief Left direction. */
#define FPDFTEXT_LEFT			-1
/** @brief Right direction. */
#define FPDFTEXT_RIGHT			1
/** @brief Up direction. */
#define FPDFTEXT_UP				-2
/** @brief Down direction. */
#define FPDFTEXT_DOWN			2

/*@}*/
class IPDF_ReflowedPage;

/**
 * @name Flags for CreateTextPage.
 */
/*@{*/
#define FPDFTEXT_WRITINGMODE_UNKNOW	0
#define FPDFTEXT_WRITINGMODE_LRTB	1
#define FPDFTEXT_WRITINGMODE_RLTB	2
#define FPDFTEXT_WRITINGMODE_TBRL	3
/*@}*/
class CPDFText_ParseOptions : public CFX_Object
{
public:
	/** Default constructor. */
	CPDFText_ParseOptions();

	FX_BOOL			m_bGetCharCodeOnly;
	FX_BOOL			m_bNormalizeObjs;
	FX_BOOL			m_bOutputHyphen;
#ifndef _FXM_OPENSOURCE_
	//<<<+++OPENSOURCE_BEGIN LIC==FOXIT
	FX_BOOL			m_bNoProcessMarkedContent;
	//<<<+++OPENSOURCE_END
#endif
};

/** @brief Text page for PDF text processing. */
class IPDF_TextPage : public CFX_Object
{
public:
	/** The destructor. */
	virtual ~IPDF_TextPage() {}
	static IPDF_TextPage*	CreateTextPage(const CPDF_Page* pPage, CPDFText_ParseOptions ParserOptions);	

/**
* Function: IPDF_TextPage::CreateTextPage
*
* Comments:
*			Get a text page handle
*
* @param[in] pPage			A PDF Page handle
* @param[in] flags			see name Flags for CreateTextPage. default is 0
*
* @retval return the text page handle
*/
	static IPDF_TextPage*	CreateTextPage(const CPDF_Page* pPage,int flags=0);	

/**
* Function: IPDF_TextPage::CreateTextPage
*
* Comments:
*			Get a text page handle
*
* @param[in] pObjs			The pdf objects List
* @param[in] flags			see name Flags for CreateTextPage. default is 0
*
* @retval return the text page handle
*/
	static IPDF_TextPage*	CreateTextPage(const CPDF_PageObjects* pObjs,int flags=0);	
/**
* Function: IPDF_TextPage::CreatReflowTextPage
*
* Comments:
*			Get a text page handle
*
* @param[in] pRefPage		A reflowed Page handle
*
* @retval return the reflowed text page handle
*/
	static IPDF_TextPage*	CreateReflowTextPage(IPDF_ReflowedPage* pRefPage);

	/** Check whether the text page has been parsed. */
	virtual void			NormalizeObjects(FX_BOOL bNormalize) =0;
	
	//The page object may have parsed content objects (by CPDF_Page::ParseContent call)
	virtual FX_BOOL			ParseTextPage() = 0;
	
	/** Check whether the text page has been parsed. */
	virtual FX_BOOL			IsParsered() const =0;

public:
	/** 
	* Function: IPDF_TextIndexMapping::CharIndexFromTextIndex
	* Get character index from text index. 
	*
	* @param[in] TextIndex 			text index form page text.
	*
	* @retval return character index, -1 is non-existent.
	*/
	virtual int CharIndexFromTextIndex(int TextIndex) const =0;

	/** 
	* Function: IPDF_TextIndexMapping::CharIndexFromTextIndex
	* Get text index from character index. 
	*
	* @param[in] CharIndex 			character index form character list.
	*
	* @retval return text index, -1 is non-existent.
	*/
	virtual int TextIndexFromCharIndex(int CharIndex) const =0;
	
	/** Get the count of character in the text page. */
	virtual int				CountChars() const = 0;
	/** Get the specified character information. */
	virtual	void			GetCharInfo(int index,FPDF_CHAR_INFO & info) const = 0;
	/** Get the rectangle array for character index interzone. [start, start+count) */
	virtual void			GetRectArray(int start, int nCount,CFX_RectArray& rectArray) const = 0;
	
/**
* Function: IPDF_TextPage::GetIndexAtPos
*
* Comments:
*			Get a text page handle
*
* @param[in] point 			a coord for text coordination
* @param[in] xTorelance		X direction Recommended value
* @param[in] yTorelance		Y direction Recommended value
*
* @retval return character index; If there are no character int this point return value <0
*/
	/**
	 * If there are no character int this point return value <0
	 * Recommended value for xTorelance or yTorelance is between 0 and 30.
	 */	
	virtual int				GetIndexAtPos(CPDF_Point point,FX_FLOAT xTorelance,FX_FLOAT yTorelance) const = 0;
	/** @see GetIndexAtPos(CPDF_Point, FX_FLOAT, FX_FLOAT) */
	virtual int				GetIndexAtPos(FX_FLOAT x,FX_FLOAT y,FX_FLOAT xTorelance,FX_FLOAT yTorelance) const = 0;
	/**
	* Function: IPDF_TextPage::GetOrderByDirection
	*
	* Comments:
	*			return the character with specified relationship of current character
	*
	* @param[in] index 			character index
	* @param[in] direction		see Directions type.
	*
	* @retval return character index ; -1 previous page,-2 for next page. 
	*/
	virtual	int				GetOrderByDirection(int index,int direction) const = 0;

	/** Get the text in specified rectangle. */
	virtual CFX_WideString	GetTextByRect(CFX_FloatRect rect) const =0;
	/** Get the text rectangle array by a rectangle. */
	virtual void			GetRectsArrayByRect(CFX_FloatRect rect,CFX_RectArray& resRectArray) const = 0;
	
	/**
	* Function: IPDF_TextPage::CountRects
	*
	* Comments:
	*			Get the count of text rectangle in the text page.
	*
	* @param[in] start 			start character index
	* @param[in] nCount			character's count
	*
	* @retval return count of text rectangle
	*/
	virtual int				CountRects(int start,int nCount)=0;
	/** Get the specified text rectangle in the text page. */
	virtual	void			GetRect(int rectIndex,FX_FLOAT& left,FX_FLOAT& top,FX_FLOAT& right,FX_FLOAT &bottom) const=0;
	/*	
	* Function: IPDF_TextPage::GetBaselineRotate
	*
	* Comments:
	* Get the specified text rotate in the text page.
	*
	* @param[in] rectIndex 		rectangle index form CountRects.
	* @param[in/out] Rotate		Get the specified text rotate.
	*							0: left to right
	*							90: bottom to top
	*							180: right to left
	*							270: top to bottom
	*
	* @retval return FALSE is indefinite
	*/
	virtual FX_BOOL			GetBaselineRotate(int rectIndex, int& Rotate) =0;
	/*	
	* Function: IPDF_TextPage::GetBaselineRotate
	*
	* Comments:
	* Get the specified text rotate in the text page.
	*
	* @param[in] rect 			The content of this rectangle should be in the same line.
	* @param[in/out] Rotate		Get the specified text rotate.
	*							0: left to right
	*							90: bottom to top
	*							180: right to left
	*							270: top to bottom
	*
	* @retval return FALSE is indefinite
	*/
	virtual FX_BOOL			GetBaselineRotate(CFX_FloatRect rect, int& Rotate) = 0;

	/**
	* Function: IPDF_TextPage::CountBoundedSegments
	*
	* Comments:
	*			Get the count of segment in specified rectangle.
	*
	* @param[in] left 			Left position of the text coordination
	* @param[in] top			Top position of the text coordination
	* @param[in] right 			Right position of the text coordination
	* @param[in] bottom			Bottom position of the text coordination
	*
	* @retval return count of segment in specified rectangle
	*/
	virtual	int				CountBoundedSegments(FX_FLOAT left,FX_FLOAT top,FX_FLOAT right,FX_FLOAT bottom, FX_BOOL bContains = FALSE)=0;
	/**
	* Function: IPDF_TextPage::CountBoundedSegments
	*
	* Comments:
	*			Get the specified bounded segment.
	*
	* @param[in] index 			segment index form CountBoundedSegments.
	* @param[in/out] start		start character index
	* @param[in/out] count 		character's count
	*/
	virtual	void			GetBoundedSegment(int index,int& start,int& count) const=0;
	
	/** not support now. */
	virtual int				GetWordBreak(int index,int direction) const=0;

	/** nCount=-1 for the end of the page. */
	virtual CFX_WideString	GetPageText(int start=0,int nCount=-1 ) const=0;
};

//////////////////////////////////////////////////////////////////////////
// IPDF_PageFind

/**
 * @name search flags.
 */
/*@{*/

/** @brief Whether to match the character case(upper/lower). */
#define FPDFTEXT_MATCHCASE      0x00000001
/** @brief Whether to match the whole word for the search pattern. */
#define FPDFTEXT_MATCHWHOLEWORD 0x00000002
/** @brief Whether to do consecutive searching. */
#define FPDFTEXT_CONSECUTIVE	0x00000004
//<<<+++OPENSOURCE_MUST_BEGIN LIC==FOXIT
/** @brief Whether to match Arabic kashida. */
#define FPDFTEXT_MATCHKASHIDA	0x00000008
//<<<+++OPENSOURCE_MUST_END
/*@}*/

/** @brief Text Search class. */
class IPDF_TextPageFind : public CFX_Object
{
public:
	/** The destructor. */
	virtual	~IPDF_TextPageFind(){}
	/** Create from a text page. */
	static	IPDF_TextPageFind*	CreatePageFind(const IPDF_TextPage* pTextPage);
public:
	/** Find the first match with specified search flags, optionally with a start position. */
	virtual	FX_BOOL				FindFirst(CFX_WideString findwhat,int flags,int startPos=0) = 0;
	/** Find the next match. */
	virtual	FX_BOOL				FindNext() = 0;
	/** Find the previous match. */
	virtual	FX_BOOL				FindPrev() = 0;

	/** Get the matched rectangle array. */
	virtual void				GetRectArray(CFX_RectArray& rects) const = 0;
	/** Get the current order. */
	virtual int					GetCurOrder() const = 0;
	/** Get the count of current matches. */
	virtual int					GetMatchedCount() const = 0;
};

//////////////////////////////////////////////////////////////////////////
//IPDF_LinkExtract

/** @brief Link extracting class. */
class IPDF_LinkExtract : public CFX_Object
{
public:
	/** The destructor. */
	virtual	~IPDF_LinkExtract(){}
	/** Create an empty link extracting object. */
	static	IPDF_LinkExtract*	CreateLinkExtract();
	/** Extract links for a text page. */
	virtual FX_BOOL				ExtractLinks(const IPDF_TextPage* pTextPage)=0;
public:
	/** Get the count of links in the text page. Return -1 for error. */
	virtual int					CountLinks() const = 0;
	/** Get the linked URL for specified link. */
	virtual CFX_WideString		GetURL(int index) const =0;
	/**
	* Comments:
	*			Get the specified bounded segment.
	*
	* @param[in] index 			segment index form CountBoundedSegments.
	* @param[in/out] start		start character index
	* @param[in/out] count 		character's count
	*/
	virtual	void				GetBoundedSegment(int index,int& start,int& count) const = 0;
	/** Get the rectangle array for specified link. */
	virtual void				GetRects(int index,CFX_RectArray& rects) const =0;
};
//<<<+++OPENSOURCE_MUST_BEGIN
#endif
//<<<+++OPENSOURCE_MUST_END
/** @} */


